#ifndef __M_CHANNEL_H__
#define __M_CHANNEL_H__
/**
 * @file m_channel.h
 * @brief 消息队列通道管理模块
 * 
 * 本模块实现 AMQP 通道的核心功能，包括：
 * 1. 交换机和队列的声明与删除
 * 2. 队列绑定与解绑
 * 3. 消息发布与确认
 * 4. 消费者订阅管理
 * 5. 通道生命周期管理
 * 
 * 包含两个核心组件：
 * 1. Channel - 通道实体，处理所有 AMQP 操作
 * 2. ChannelManager - 通道管理器，维护所有活跃通道
 */
#include "muduo/net/TcpConnection.h"
#include "muduo/proto/codec.h"
#include "muduo/proto/dispatcher.h"
#include "../common/logger.hpp"
#include "../common/helper.hpp"
#include "../common/msg.pb.h"
#include "../common/proto.pb.h"
#include "../common/threadpool.hpp"
#include "consumer.hpp"
#include "host.hpp"
#include "route.hpp"

namespace bitmq 
{
    /// 协议相关智能指针别名定义
    using ProtobufCodecPtr = std::shared_ptr<ProtobufCodec>;
    using openChannelRequestPtr = std::shared_ptr<openChannelRequest>;
    using closeChannelRequestPtr = std::shared_ptr<closeChannelRequest>;
    using declareExchangeRequestPtr = std::shared_ptr<declareExchangeRequest>;
    using deleteExchangeRequestPtr = std::shared_ptr<deleteExchangeRequest>;
    using declareQueueRequestPtr = std::shared_ptr<declareQueueRequest>;
    using deleteQueueRequestPtr = std::shared_ptr<deleteQueueRequest>;
    using queueBindRequestPtr = std::shared_ptr<queueBindRequest>;
    using queueUnBindRequestPtr = std::shared_ptr<queueUnBindRequest>;
    using basicPublishRequestPtr = std::shared_ptr<basicPublishRequest>;
    using basicAckRequestPtr = std::shared_ptr<basicAckRequest>;
    using basicConsumeRequestPtr = std::shared_ptr<basicConsumeRequest>;
    using basicCancelRequestPtr = std::shared_ptr<basicCancelRequest>;
    
    /**
     * @class Channel
     * @brief AMQP 通道实现类
     * 
     * 表示一个 AMQP 通信通道，负责处理所有 AMQP 协议操作：
     * - 交换机和队列的生命周期管理
     * - 消息路由和发布
     * - 消费者订阅管理
     * - 消息确认机制
     * 
     * 每个通道关联一个 TCP 连接，支持多线程操作。
     */
    class Channel 
    {
        public:
            using ptr = std::shared_ptr<Channel>; ///< 智能指针别名
            
            /**
             * @brief 构造函数
             * @param id 通道唯一标识
             * @param host 虚拟主机指针
             * @param cmp 消费者管理器指针
             * @param codec 协议编解码器
             * @param conn TCP 连接对象
             * @param pool 线程池指针
             */
            Channel(const std::string &id, 
                const VirtualHost::ptr &host, 
                const ConsumerManager::ptr &cmp, 
                const ProtobufCodecPtr &codec, 
                const muduo::net::TcpConnectionPtr &conn,
                const threadpool::ptr &pool):
                _cid(id),
                _conn(conn),
                _codec(codec),
                _cmp(cmp),
                _host(host),
                _pool(pool){
                DLOG("New Channel: %p", this);
            }
            
            /**
             * @brief 析构函数
             * 
             * 自动清理关联的消费者
             */
            ~Channel() 
            {
                if (_consumer) 
                {
                    _cmp->remove(_consumer->tag, _consumer->qname);
                }
                DLOG("Delete Channel: %p", this);
            }
            
            /**
             * @brief 声明交换机
             * @param req 声明交换机请求
             */
            void declareExchange(const declareExchangeRequestPtr &req) 
            {
                bool ret = _host->declareExchange(
                    req->exchange_name(), 
                    req->exchange_type(), 
                    req->durable(), 
                    req->auto_delete(), 
                    req->args());
                    
                basicResponse(ret, req->rid(), req->cid());
            }
            
            /**
             * @brief 删除交换机
             * @param req 删除交换机请求
             */
            void deleteExchange(const deleteExchangeRequestPtr &req) 
            {
                _host->deleteExchange(req->exchange_name());
                basicResponse(true, req->rid(), req->cid());
            }
            
            /**
             * @brief 声明队列
             * @param req 声明队列请求
             * 
             * 成功声明队列后初始化消费者管理
             */
            void declareQueue(const declareQueueRequestPtr &req) 
            {
                bool ret = _host->declareQueue(
                    req->queue_name(),
                    req->durable(), 
                    req->exclusive(),
                    req->auto_delete(), 
                    req->args());
                    
                if (!ret) 
                {
                    basicResponse(false, req->rid(), req->cid());
                    return;
                }
                
                // 初始化队列的消费者管理
                _cmp->initQueueConsumer(req->queue_name());
                basicResponse(true, req->rid(), req->cid());
            }
            
            /**
             * @brief 删除队列
             * @param req 删除队列请求
             * 
             * 删除队列前销毁关联的消费者管理
             */
            void deleteQueue(const deleteQueueRequestPtr &req) 
            {
                _cmp->destroyQueueConsumer(req->queue_name());
                _host->deleteQueue(req->queue_name());
                basicResponse(true, req->rid(), req->cid());
            }
            
            /**
             * @brief 队列绑定
             * @param req 队列绑定请求
             */
            void queueBind(const queueBindRequestPtr &req) 
            {
                bool ret = _host->bind(
                    req->exchange_name(), 
                    req->queue_name(), 
                    req->binding_key());
                    
                basicResponse(ret, req->rid(), req->cid());
            }
            
            /**
             * @brief 队列解绑
             * @param req 队列解绑请求
             */
            void queueUnBind(const queueUnBindRequestPtr &req) 
            {
                _host->unBind(req->exchange_name(), req->queue_name());
                basicResponse(true, req->rid(), req->cid());
            }
            
            /**
             * @brief 发布消息
             * @param req 发布消息请求
             * 
             * 实现消息路由、队列存储和消费任务调度
             */
            void basicPublish(const basicPublishRequestPtr &req) 
            {
                // 1. 验证交换机存在
                auto ep = _host->selectExchange(req->exchange_name());
                if (!ep) 
                {
                    basicResponse(false, req->rid(), req->cid());
                    return;
                }
                
                // 2. 提取消息属性和路由键
                BasicProperties *properties = nullptr;
                std::string routing_key;
                if (req->has_properties()) 
                {
                    properties = req->mutable_properties();
                    routing_key = properties->routing_key();
                }
                
                // 3. 获取交换机绑定信息
                MsgQueueBindingMap mqbm = _host->exchangeBindings(req->exchange_name());
                
                // 4. 路由匹配和消息分发
                for (auto &binding : mqbm) 
                {
                    if (Router::route(ep->type, routing_key, binding.second->binding_key)) 
                    {
                        // 存储消息到队列
                        _host->basicPublish(binding.first, properties, req->body());
                        
                        // 提交消费任务到线程池
                        auto task = std::bind(&Channel::consume, this, binding.first);
                        _pool->push(task);
                    }
                }
                
                basicResponse(true, req->rid(), req->cid());
            }
            
            /**
             * @brief 消息确认
             * @param req 消息确认请求
             */
            void basicAck(const basicAckRequestPtr &req) 
            {
                _host->basicAck(req->queue_name(), req->message_id());
                basicResponse(true, req->rid(), req->cid());
            }
            
            /**
             * @brief 订阅队列
             * @param req 订阅请求
             * 
             * 将当前通道注册为消费者
             */
            void basicConsume(const basicConsumeRequestPtr &req) 
            {
                // 1. 验证队列存在
                if (!_host->existsQueue(req->queue_name())) 
                {
                    basicResponse(false, req->rid(), req->cid());
                    return;
                }
                
                // 2. 创建消费者回调
                auto cb = std::bind(&Channel::callback, this, 
                    std::placeholders::_1,
                    std::placeholders::_2, 
                    std::placeholders::_3);
                    
                // 3. 注册消费者
                _consumer = _cmp->create(
                    req->consumer_tag(), 
                    req->queue_name(), 
                    req->auto_ack(), 
                    cb);
                    
                basicResponse(true, req->rid(), req->cid());
            }
            
            /**
             * @brief 取消订阅
             * @param req 取消订阅请求
             */
            void basicCancel(const basicCancelRequestPtr &req) 
            {
                _cmp->remove(req->consumer_tag(), req->queue_name());
                basicResponse(true, req->rid(), req->cid());
            }
            
        private:
            /**
             * @brief 消费者回调函数
             * @param tag 消费者标识
             * @param bp 消息属性
             * @param body 消息内容
             * 
             * 将接收到的消息封装为协议格式发送给客户端
             */
            void callback(const std::string tag, const BasicProperties *bp, const std::string &body) 
            {
                basicConsumeResponse resp;
                resp.set_cid(_cid);
                resp.set_body(body);
                resp.set_consumer_tag(tag);
                
                if (bp) 
                {
                    resp.mutable_properties()->set_id(bp->id());
                    resp.mutable_properties()->set_delivery_mode(bp->delivery_mode());
                    resp.mutable_properties()->set_routing_key(bp->routing_key());
                }
                
                _codec->send(_conn, resp);
            }
            
            /**
             * @brief 消费消息任务
             * @param qname 队列名称
             * 
             * 从队列获取消息并分发给消费者
             */
            void consume(const std::string &qname) 
            {
                // 1. 从队列获取消息
                MessagePtr mp = _host->basicConsume(qname);
                if (!mp) 
                {
                    DLOG("Consume failed: No messages in queue %s", qname.c_str());
                    return;
                }
                
                // 2. 选择消费者
                Consumer::ptr cp = _cmp->choose(qname);
                if (!cp) 
                {
                    DLOG("Consume failed: No consumers for queue %s", qname.c_str());
                    return;
                }
                
                // 3. 调用消费者回调
                cp->callback(cp->tag, mp->mutable_payload()->mutable_properties(), mp->payload().body());
                
                // 4. 自动确认处理
                if (cp->auto_ack) 
                {
                    _host->basicAck(qname, mp->payload().properties().id());
                }
            }
            
            /**
             * @brief 发送基础响应
             * @param ok 操作结果
             * @param rid 请求ID
             * @param cid 通道ID
             */
            void basicResponse(bool ok, const std::string &rid, const std::string &cid) 
            {
                basicCommonResponse resp;
                resp.set_rid(rid);
                resp.set_cid(cid);
                resp.set_ok(ok);
                _codec->send(_conn, resp);
            }
            
        private:
            std::string _cid;                       ///< 通道唯一标识
            Consumer::ptr _consumer;                ///< 关联的消费者（当通道作为消费者时）
            muduo::net::TcpConnectionPtr _conn;     ///< TCP 连接对象
            ProtobufCodecPtr _codec;                ///< 协议编解码器
            ConsumerManager::ptr _cmp;              ///< 消费者管理器
            VirtualHost::ptr _host;                 ///< 虚拟主机
            threadpool::ptr _pool;                  ///< 线程池
    };

    /**
     * @class ChannelManager
     * @brief 通道管理类
     * 
     * 管理所有活跃的 AMQP 通道，提供通道的创建、销毁和检索功能。
     * 线程安全设计，支持并发操作。
     */
    class ChannelManager 
    {
        public:
            using ptr = std::shared_ptr<ChannelManager>; ///< 智能指针别名
            
            /// 默认构造函数
            ChannelManager() = default;
            
            /**
             * @brief 创建新通道
             * @param id 通道ID
             * @param host 虚拟主机指针
             * @param cmp 消费者管理器指针
             * @param codec 协议编解码器
             * @param conn TCP连接对象
             * @param pool 线程池指针
             * @return 创建成功返回true，通道已存在返回false
             */
            bool openChannel(const std::string &id, 
                const VirtualHost::ptr &host, 
                const ConsumerManager::ptr &cmp, 
                const ProtobufCodecPtr &codec, 
                const muduo::net::TcpConnectionPtr &conn,
                const threadpool::ptr &pool) 
            {
                std::unique_lock<std::mutex> lock(_mutex);
                if (_channels.find(id) != _channels.end()) 
                {
                    DLOG("Channel already exists: %s", id.c_str());
                    return false;
                }
                
                auto channel = std::make_shared<Channel>(id, host, cmp, codec, conn, pool);
                _channels.emplace(id, channel);
                return true;
            }
            
            /**
             * @brief 关闭通道
             * @param id 通道ID
             */
            void closeChannel(const std::string &id)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                _channels.erase(id);
            }
            
            /**
             * @brief 获取通道指针
             * @param id 通道ID
             * @return 找到返回通道指针，未找到返回空指针
             */
            Channel::ptr getChannel(const std::string &id) 
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _channels.find(id);
                return (it != _channels.end()) ? it->second : Channel::ptr();
            }
            
        private:
            std::mutex _mutex; ///< 线程安全互斥锁
            /// 通道映射表 <通道ID, 通道指针>
            std::unordered_map<std::string, Channel::ptr> _channels;
    };
}

#endif